<?php
namespace my;
// 前后分离验证码
use think\facade\Cache;
class Captcha
{

    // 验证码过期时间（s）
    protected $expire = 300;
    // 验证码字体大小(px)
    protected $fontSize;
    // 验证码图片宽度
    protected $imageW;
    // 验证码图片高度
    protected $imageH;
    // 验证码位数
    protected $length;
    // 字符类型 1.纯数字 2.纯字母 3.混合
    protected $type;
    // 验证码字体
    protected $fontttf = 'static/src/fonts/ELEGGARI.TTF';
    // 1. 直接输出 2. 输出base64
    protected $output;

    protected $key_prefix="captcha:";

    /**
     * 架构方法 设置参数
     */
    public function __construct($config = [])
    {
        $this->imageW = $config['width'] ?? 250;
        $this->imageH = $config['height'] ?? 80;
        $this->type = $config['type'] ?? 2;
        $this->length = $config['length'] ?? 4;
        $this->fontsize = $config['fontsize'] ?? 30;
        $this->output = $config['output'] ?? 1;
    }


    /**
     * 输出验证码并把验证码的值保存的session中
     */
    public function create()
    {
        $image = imagecreatetruecolor($this->imageW,$this->imageH);
        $white = imagecolorallocate($image,255,255,255);
        imagefilledrectangle($image,0,0,$this->imageW,$this->imageH,$white);
        $str = '';
        //匹配验证码字符类型
        switch($this->type) {
            case 0:
                $str = join('',array_rand(range(0,9),$this->length));
                break;
            case 1:
                $str = join('',array_rand(array_flip(array_merge(range('a','z'),range('A','Z'))),$this->length));
                break;
            case 2:
                $str = join('',array_rand(array_flip(array_merge(range('a','z'),range('A','Z'),range(0,9))),$this->length));
                break;
        }
        for($i=0;$i<$this->length;$i++) {
            imagettftext($image,$this->fontsize,mt_rand(-30,30),$i*($this->imageW/$this->length)+5,mt_rand(($this->imageH/2)+($this->fontsize/2),($this->imageH/2)+($this->fontsize/2)),$this->randColor($image),$this->fontttf,$str[$i]);
        }
        //添加像素点
        for ($i=1;$i<=100;$i++) {
            imagesetpixel($image,mt_rand(0,$this->imageW),mt_rand(0,$this->imageH),$this->randColor($image));
        }

        // 返回base64图片
        if($this->output === 1) {
            //输出后销毁图片
            header('Content-Type:image/png');
            imagepng($image);
            imagedestroy($image);
            Cache::set($this->key_prefix . $str,time(),$this->expire);
        }else {
            ob_start();
            imagepng($image);
            $image_data = ob_get_contents();
            ob_end_clean();
            $base64 = base64_encode($image_data);
            $captcha_key = randomkeys(8);
            Cache::set($this->key_prefix . $captcha_key,$str,$this->expire);
            return [
                'base64' => $base64,
                'captcha_key' => $captcha_key,
                'base64_prefix' => 'data:image/png;base64,',
            ];
        }
    }

    /**
     * 验证验证码是否正确
     */
    public function check(string $code, string $captcha_key=''): bool
    {

        if($this->output === 1) { // 验证方法 [直接输出验证码]
//            $code = mb_strtolower($code, 'UTF-8');
            $code_exist = Cache::get($this->key_prefix . $code);
            if (!$code_exist) {
                return false;
            }else {
                Cache::delete($this->key_prefix . $code);
                return true;
            }
        }else { // 验证方法 [base64 验证码]
            $code_exist = Cache::get($this->key_prefix . $captcha_key);
            if (!$code_exist) {
                return false;
            }else {
                if($code_exist !== $code) {
                    return false;
                }
                Cache::delete($this->key_prefix . $captcha_key);
                return true;
            }
        }

    }

    /**
     * 随机颜色
     */
    public function randColor($image) {
        return imagecolorallocate($image,mt_rand(0,255),mt_rand(0,255),mt_rand(0,255));
    }




}
